//
//  ETH+Account+BIP44.swift
//  XHWalletUtils
//
//  Created by xinph on 2020/5/16.
//  Copyright © 2020 xinph. All rights reserved.
//

import Foundation

extension ETH: BIP44 {
    public static func createWallet(_ path: String?, password: String, name: String = "ETH Wallet", mnemonics: String) -> coswift.Promise<Wallet> {
        let promise = coswift.Promise<Wallet>()
        
        guard let path = path, !mnemonics.isEmpty, mnemonics.split(separator: " ").count >= 12 else {
            promise.reject(error: XHError(mnemonicsLengthError))
            return promise
        }
        let keystore: BIP32Keystore
        let keyData: Data
        do {
            keystore = try BIP32Keystore(
                mnemonics: mnemonics,
                password: password,
                mnemonicsPassword: "",
                language: .english,
                prefixPath: path)!
            keyData = try JSONEncoder().encode(keystore.keystoreParams)
        } catch {
            promise.reject(error: XHError(mnemonicsError))
            return promise
        }
        let name = name.isEmpty ? "Wallet ETH" : name
        let address = keystore.addresses!.first!.address
        let account = Account(name, address: address, coin: 60)
        
        var privateKey = ""
        var publicKey = ""

        let wallet = ETH(mnemonics, keystore: keyData, path: CoinBIP44.defaultETHPath, isHD: true, privateKey: privateKey, publicKey: publicKey)

        co_launch {
            let result = try await(promise: wallet.UNSAFE_getPrivateAndPublicKey(password: password, address: address))
            switch result {
            case let .fulfilled(key):
                wallet.privateKey = key.pri
                wallet.publicKey = key.pub
                Manager.IO.writeWallet(account, wallet: wallet)
                _ = wallet.generateWeb3()
                promise.fulfill(value: wallet)
            default: break
            }
        }
        return promise
    }
    
    public func createNewAccount(_ password: String, name: String = "Account \((Manager.shared.wallets?[CoinBIP44.defaultETHPath]?.accounts.count ?? 0)+1)", cache write: Bool = true, closure: @escaping (Result<Account>) -> Void) {
        guard self.isHDWallet, let keystore = self.ethKeystore else { return closure(Result.failure(XHError(notSuppurt))) }
        do {
            /// 更新keystore
            try keystore.createNewChildAccount(password: password)
            let newAddress = keystore.paths.sorted(by: {$0.0 < $1.0}).last?.value.address
            let account = Account(name, address: newAddress!, coin: 60)
            guard write else { closure(Result.success(account)); return }
            guard self.accounts.last?.address != account.address else {
                closure(Result.failure(XHError(createAccountFailure)))
                return
            }
            /// 更新磁盘与缓存
            Manager.IO.writeWallet(account, wallet: self)
            closure(Result.success(account))
        } catch (let err) {
            closure(Result.failure(XHError(err: err)))
            print(err)
        }
    }
    
    public func createSevralAccounts(_ password: String, need count: UInt64, cache write: Bool = false) {
        guard count > 0 else { return }
        var accounts: [Account] = []
        for _ in 0..<count {
            createNewAccount(password, cache: write) {
                if case Result.success(let act) = $0 {
                    accounts.append(act)
                }
            }
        }
    }
}
